#ifndef __HEADER_JSON__
#define __HEADER_JSON__

#include <stdlib.h>
#include "crypto/types.h"
#include "crypto/errors.h"

#define JSON_KEY_LENGTH 64
#define JSON_PAYLOAD 0.75
#define JSON_DEFAULT_INITIAL_CAPACITY (1 << 4)
#define JSON_ARRAY_INITIAL_CAPACITY 20
/*
 * Json Item
 */

enum json_value_type
{
    JSON_VALUE_TYPE_INVALI,
    JSON_VALUE_TYPE_NUL,
    JSON_VALUE_TYPE_LONG,
    JSON_VALUE_TYPE_DOUBLE,
    JSON_VALUE_TYPE_STRING,
    JSON_VALUE_TYPE_ARRAY,
    JSON_VALUE_TYPE_JSON
};
typedef enum json_value_type JsonValueType;

// Initial cap in json parse(src/parse/json/json.y rule: _JOSN_ARRAY) is 20. The growth curve is in line with exponential growth with a base of 2.
struct json_array
{
    JsonValueType type;
    int cap;
    int len;
    void *array;
};
typedef struct json_array JsonArray;

struct json_value
{
    JsonValueType type;
    void *value;
};
typedef struct json_value JsonValue;

struct json_item
{
    char key[JSON_KEY_LENGTH];
    uint hash;
    JsonValue *value;
};
typedef struct json_item JsonItem;

struct json_binary_tree
{
    void *left;
    void *right;
};

/*
 *  Json Index
 */

typedef struct json_binary_tree BinaryTree;

struct json_link_list
{
    void *next;
};
typedef struct json_link_list LinkList;

union json_index_meth
{
    LinkList linkList;
    BinaryTree binaryTree;
};
typedef union json_index_meth JsonIndexMeth;

struct json_index_item
{
    JsonIndexMeth index;
    JsonItem *item;
};
typedef struct json_index_item JsonIndexItem;

enum json_entry_data_struct_type
{
    JSON_DATA_STRUCT_LINKLIST,
    JSON_DATA_STRUCT_BINARYTREE
};
typedef enum json_entry_data_struct_type JsonEntryDataStructType;

struct json_entry
{
    int len;
    JsonEntryDataStructType type;
    JsonIndexItem *indexItem;
};
typedef struct json_entry JsonEntry;

struct _json
{
    int cap; // the number of entries
    int len; // the number of jsonItem member
    JsonEntry *entrys;
};
typedef struct _json Json;

void JsonFree(Json *json);
void JsonItemFree(JsonItem *jsonItem);
Json *JsonInit();
JsonValue *JsonValueInit(JsonValueType jsonValueType);
JsonItem *JsonItemInit(char *key, JsonValue *value);
JsonItem *JsonStringItemInit(char *key, char *data);
JsonItem *JsonNumberInit(char *key, int64 data);
JsonItem *JsonDoubleInit(char *key, double data);
JsonArray *JsonArrayInit();
bool JsonPut(Json *json, JsonItem *jsonItem);
bool JsonRemove(Json *json, char *key);
JsonItem *JsonItemInit(char *key, JsonValue *value);
static void JsonArrayStringify(JsonArray *jsonArray, char *buffer);
static void JsonEntryStringify(JsonEntry *jsonEntry, char *buffer);
char *JsonString(Json *json, char *buffer);
Json *JsonParse(char *jsonString);
JsonItem *JsonGet(Json *json, char *key);

#endif